#include "gtest/gtest.h"
#include "DoubleLinkList.h"

// 测试链表初始化状态
TEST(DoubleLinkListTest, InitialState) {
    DoubleLinkList list;
    EXPECT_TRUE(list.Empty());
    EXPECT_EQ(list.Size(), 0);
}

// 测试 PushFront（头插法）
TEST(DoubleLinkListTest, PushFront) {
    DoubleLinkList list;
    list.PushFront(10);
    list.PushFront(20);
    list.PushFront(30);
    EXPECT_EQ(list.Size(), 3);
    EXPECT_EQ(list.Get(1), 30);
    EXPECT_EQ(list.Get(2), 20);
    EXPECT_EQ(list.Get(3), 10);
}

// 测试 PushBack（尾插法）
TEST(DoubleLinkListTest, PushBack) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    EXPECT_EQ(list.Size(), 3);
    EXPECT_EQ(list.Get(1), 1);
    EXPECT_EQ(list.Get(2), 2);
    EXPECT_EQ(list.Get(3), 3);
}

// 测试 PopFront（删除头节点）
TEST(DoubleLinkListTest, PopFront) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    list.PopFront();
    EXPECT_EQ(list.Size(), 2);
    EXPECT_EQ(list.Get(1), 2);
    EXPECT_EQ(list.Get(2), 3);
}

// 测试 PopBack（删除尾节点）
TEST(DoubleLinkListTest, PopBack) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    list.PopBack();
    EXPECT_EQ(list.Size(), 2);
    EXPECT_EQ(list.Get(1), 1);
    EXPECT_EQ(list.Get(2), 2);
}

// 测试 Insert（在指定位置插入）
TEST(DoubleLinkListTest, Insert) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(3);
    list.Insert(2, 2); // 在位置 2 插入 2
    EXPECT_EQ(list.Size(), 3);
    EXPECT_EQ(list.Get(1), 1);
    EXPECT_EQ(list.Get(2), 2);
    EXPECT_EQ(list.Get(3), 3);
}

// 测试 Remove（删除第一个匹配的元素）
TEST(DoubleLinkListTest, Remove) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    list.PushBack(2);
    list.Remove(2);
    EXPECT_EQ(list.Size(), 3);
    EXPECT_EQ(list.Get(1), 1);
    EXPECT_EQ(list.Get(2), 3);
    EXPECT_EQ(list.Get(3), 2);
}

// 测试 RemoveAll（删除所有匹配的元素）
TEST(DoubleLinkListTest, RemoveAll) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(2);
    list.PushBack(3);
    list.RemoveAll(2);
    EXPECT_EQ(list.Size(), 2);
    EXPECT_EQ(list.Get(1), 1);
    EXPECT_EQ(list.Get(2), 3);
}

// 测试 Set（修改指定位置元素的值）
TEST(DoubleLinkListTest, Set) {
    DoubleLinkList list;
    list.PushBack(10);
    list.PushBack(20);
    list.PushBack(30);
    list.Set(2, 99);
    EXPECT_EQ(list.Get(2), 99);
}

// 测试 Find（查找是否存在某个元素）
TEST(DoubleLinkListTest, Find) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    EXPECT_TRUE(list.Find(2));
    EXPECT_FALSE(list.Find(4));
}

// 测试 Clear（清空链表）
TEST(DoubleLinkListTest, Clear) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    list.Clear();
    EXPECT_TRUE(list.Empty());
    EXPECT_EQ(list.Size(), 0);
}

// 测试 Get 越界
TEST(DoubleLinkListTest, GetOutOfRange) {
    DoubleLinkList list;
    list.PushBack(1);
    EXPECT_THROW(list.Get(2), std::out_of_range);  // pos 越界
}

// 测试 Set 越界
TEST(DoubleLinkListTest, SetOutOfRange) {
    DoubleLinkList list;
    list.PushBack(1);
    EXPECT_THROW(list.Set(2, 10), std::out_of_range);  // pos 越界
}

// 测试空链表操作
TEST(DoubleLinkListTest, EmptyListOperations) {
    DoubleLinkList list;
    EXPECT_TRUE(list.Empty());
    EXPECT_EQ(list.Size(), 0);
    list.PopFront();  // 空链表调用 PopFront
    list.PopBack();   // 空链表调用 PopBack
    EXPECT_FALSE(list.Find(1));  // 空链表查找元素
    EXPECT_THROW(list.Get(1), std::out_of_range);  // 空链表 Get 越界
    EXPECT_THROW(list.Set(1, 100), std::out_of_range);  // 空链表 Set 越界
}

// 测试正向打印
TEST(DoubleLinkListTest, PrintForward) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    // PrintForward() 会直接输出到控制台，无法直接 ASSERT
    // 但可以手动检查控制台输出，或者修改为返回一个字符串并比较
}

// 测试反向打印
TEST(DoubleLinkListTest, PrintBackward) {
    DoubleLinkList list;
    list.PushBack(1);
    list.PushBack(2);
    list.PushBack(3);
    // PrintBackward() 会直接输出到控制台，无法直接 ASSERT
    // 但可以手动检查控制台输出，或者修改为返回一个字符串并比较
}

int main() {
    ::testing::InitGoogleTest();
    return RUN_ALL_TESTS();
}